﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;

namespace ActionFilter1
{

    /***
     *   需求:
     *   1.ActionFilter可以在满足条件的时候终止操作方法的执行
     *   2.在ActionFilter中,如果我们不调用await next(),就可以终止Action方法的执行了
     *   3.为了避免恶意客户端频繁发送大量请求消耗服务器资源,我们要实现"一秒钟内只允许最多有一个来自
     *   同一个IP地址的请求"
     */
    public class RateLimitActionFilter : IAsyncActionFilter
    {
        private readonly IMemoryCache memCache;
        public RateLimitActionFilter(IMemoryCache memCache)
        {
            this.memCache = memCache;
        }

        public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var remoteIP = context.HttpContext.Connection.RemoteIpAddress!.ToString();
            string cacheKey = $"LastVisitTick_{remoteIP}";
            long? lastTick = memCache.Get<long?>(cacheKey);
            //tick为null或大于当前环境tick的1000毫秒
            if (lastTick == null || Environment.TickCount64 - lastTick > 1000)
            {
                //设置缓存过期时间10秒,避免长期不访问的用户长期占用缓存内存
                memCache.Set(cacheKey, Environment.TickCount64, DateTimeOffset.Now.AddSeconds(10));
                return next(); //继续执行
            }


            context.Result = new ContentResult() { StatusCode = 429,Content="访问太频繁!" }; //429代表频繁访问
            return Task.CompletedTask;
        }
    }
}
